#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <omp.h>

#define TAM_STRING 45
#define NUMTHREAD 4

void zera_string(char *c, int n)
{
    int i = 0;

    for(i = 0; i < n; i++)
        c[i] = 0;
}

int palindromo(char *str) {

    int tam = strlen(str);
    int i;
    int j;
    int k;
    int soma_ascii = 0;

    i=0;
    j=tam-1;

    //ignora caracteres especiais no final de palavra;
    for(k = j; k >= 0; k--)
        if((int)str[k] < 65 || ((int)str[k] > 90 && (int)str[k] < 97) || (int)str[k] > 122)
        {
            if(str[k]==',')
                str[k]=0;

            j--;
        }
        else
            break;

    //ignora caracteres especiais no início de palavra;
    for(k = 0; k <= j; k++)
        if((int)str[k] < 65 || ((int)str[k] > 90 && (int)str[k] < 97) || (int)str[k] > 122)
            i++;
        else
            break;

    //teste se é palíndromo;
    if(j == -1)
        return 0;
    for ( ; i < j; i++)
    {
        if(((int)str[j] != (int)str[i]) && ((int)str[j]+32 != (int)str[i]) && ((int)str[j] != (int)str[i]+32))
            return 0;
        j--;
    }

    return 1;
}

int main(int argc, char *argv[]) {

    FILE *fp;
    clock_t t;
    char aux[TAM_STRING];
    char **texto = (char**)malloc(sizeof(char*));
    char *frase = (char*)malloc(sizeof(char));
    int i = 0;
    int j = 0;
    int n = 0;
    int palin = 0;
    int chunk = 0;
    int pf = 0;
    int tam_frase = 0;
    int n_frase = 0;

    if((fp = fopen("shakespe.txt","r")) == NULL)
    {
        printf("Erro.\n");
        exit(1);
    }

    omp_set_num_threads(NUMTHREAD);
    zera_string(aux,TAM_STRING);

    for(i = 0; !feof(fp); i++)
    {
        fscanf(fp,"%s",aux);
        texto = (char**)realloc(texto,sizeof(char*)*(n+1));
        texto[i] = (char*)malloc(sizeof(char)*(strlen(aux)+1));
        strcpy(texto[i],aux);
        zera_string(aux,TAM_STRING);
        n++;
    }

    //chunk = n/NUMTHREAD >= 1 ? n/NUMTHREAD : 1;
    if(n/NUMTHREAD >= 1)
        chunk = n/NUMTHREAD;
    else
        chunk = 1;

    //marca o clock inicial da execução do algoritmo;
    t = clock();
    #pragma omp parallel shared(texto,chunk,n) firstprivate(i) reduction(+:palin)
    {
        #pragma omp for schedule(dynamic,chunk) nowait
        for(i = 0; i < n-1; i++)
            palin += palindromo(texto[i]);
    }

    //carrega as frases
    tam_frase = 1;
    zera_string(frase,tam_frase);

    for(i=0; i< n-1; i++ )
    {
       tam_frase += strlen(texto[i]);
       frase = (char*)realloc(frase,sizeof(char)*tam_frase);
       strcat(frase,texto[i]);
       zera_string(texto[i],strlen(texto[i]));
       texto[i] = (char*)realloc(texto[i],sizeof(char)*1);
       if(frase[strlen(frase)-1] == '.' || frase[strlen(frase)-1] == ':' || frase[strlen(frase)-1] == '?' || frase[strlen(frase)-1] == '!')
       {
            texto[n_frase] = (char*)realloc(texto[n_frase],sizeof(char)*tam_frase);
            strcat(texto[n_frase],frase);
            n_frase++;
            zera_string(frase,tam_frase);
            tam_frase=1;
       }
    }

    #pragma omp parallel shared(texto,chunk,n_frase) firstprivate(i) reduction(+:pf)
    {
        #pragma omp for schedule(dynamic,chunk) nowait
        for ( i = 0; i < n_frase -1; i++ )
            pf += palindromo(texto[i]);
    }

    //calcula o numero clocks necessário para executar o algoritmo;
    t = clock() - t;
    printf("\nTempo de execucao : %.5f s \n\n", (double) t / CLOCKS_PER_SEC);

    printf("Palindromo palavra: %d\n", palin);
    printf("Palindromo frase: %d\n", pf);
    free(*texto);
    free(texto);
    fclose(fp);

    fflush(stdout);

    return 0;
}
